#pragma once
#include <iostream>
#include <vector>
#include <atomic>
#include <mutex>

#ifdef NO_MUTEX
class DeQueue
{
public:
	DeQueue(size_t size)
		: _dequeue(size)
		, _en_queue(0)
		, _de_queue(0)
	{
        std::cout << "无锁队列" << std::endl;
		mask = size - 1;
	}


	bool push(int val)
	{

		size_t pos;
		while (true)
		{
			pos = _en_queue.load(std::memory_order_relaxed);

			if (((pos + 1) & mask) == _de_queue.load())
			{
				return false;
			}

			if (_en_queue.compare_exchange_weak(pos, (pos + 1) & (_dequeue.size() - 1), std::memory_order_relaxed))
			{
				break;
			}
		}

		_dequeue[pos] = val;
		return true;
	}

	int pop()
	{
		size_t pos;
		while (true)
		{
			pos = _de_queue.load(std::memory_order_relaxed);

			if (pos == _en_queue.load(std::memory_order_relaxed))
			{
				return -1;
			}

			if (_de_queue.compare_exchange_weak(pos, (pos + 1) & (_dequeue.size() - 1), std::memory_order_relaxed))
			{
				break;
			}
		}

		return _dequeue[pos];
	}


	~DeQueue()
	{

	}
private:

    DeQueue(DeQueue&) = delete;
    DeQueue& operator=(DeQueue&) = delete;

    typedef char cacheline[64];

	size_t mask;
    cacheline pad1;
	std::vector<int> _dequeue;
    cacheline pad2;
	std::atomic<size_t> _en_queue;
    cacheline pad3;
	std::atomic<size_t> _de_queue;
};
#endif

#ifndef NO_MUTEX
class DeQueue
{
public:
	DeQueue(size_t size)
		: _dequeue(size)
		, _en_queue(0)
		, _de_queue(0)
	{
        std::cout << "有锁队列" << std::endl;
		mask = size - 1;
	}


	bool push(int val)
	{
		std::unique_lock<std::mutex> ul(_mtx);
		size_t pos = _en_queue;

		if (((pos + 1) & mask) == _de_queue)
		{
			return false;
		}

		_en_queue = (_en_queue + 1) & mask;

		_dequeue[pos] = val;
		return true;
	}

	int pop()
	{
		std::unique_lock<std::mutex> ul(_mtx);
		size_t pos = _de_queue;

		if (pos == _en_queue)
		{
			return -1;
		}

		_de_queue = (_de_queue + 1) & mask;
		
		return _dequeue[pos];
	}


	~DeQueue()
	{

	}
private:
	size_t mask;
	std::vector<int> _dequeue;
	size_t _en_queue;
	size_t _de_queue;
	std::mutex _mtx;
};
#endif